package com.zhentao.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.crypto.digest.BCrypt;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhentao.admin.utils.AdminUserThreadLocalUtils;
import com.zhentao.common.admin.rbac.SysUserParams;
import com.zhentao.common.admin.utils.AdminUserPermissionUtils;
import com.zhentao.common.user.UserCommon;
import com.zhentao.mapper.SysDeptMapper;
import com.zhentao.mapper.SysPermissionMapper;
import com.zhentao.mapper.SysRoleMapper;
import com.zhentao.mapper.SysUserMapper;
import com.zhentao.mapper.*;

import com.zhentao.minio.service.impl.MinioFileStorageServiceImpl;
import com.zhentao.model.admin.dept.SysDept;
import com.zhentao.model.admin.dto.SysUserDto;
import com.zhentao.model.admin.dto.UserDto;
import com.zhentao.model.admin.rbac.SysPermission;
import com.zhentao.model.admin.rbac.SysRole;
import com.zhentao.model.admin.rbac.SysUser;
import com.zhentao.model.admin.vo.ChargeAdminUserVo;
import com.zhentao.model.admin.rbac.SysUserRole;
import com.zhentao.model.common.dtos.PermissionResult;
import com.zhentao.model.common.dtos.ResponseResult;
import com.zhentao.model.common.enums.AppHttpCodeEnum;
import com.zhentao.model.pojo.par.dto.ChargeParOrdersDto;
import com.zhentao.model.pojo.user.ChargeUser;
import com.zhentao.model.pojo.user.gift.ChargeUserGift;
import com.zhentao.model.pojo.user.yichang.ChargeUserExpeciton;
import com.zhentao.service.SysUserService;
import com.zhentao.user.ChargeUserFeignApi;
import com.zhentao.utils.JwtService;
import com.zhentao.utils.RedisIdWorker;
import lombok.SneakyThrows;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.zhentao.common.admin.enums.AdminPermsEnum.SYS_COUPON_SELECT;
import static com.zhentao.common.admin.rbac.SysAdminCommon.*;
import static com.zhentao.model.common.enums.AppHttpCodeEnum.SERVER_ERROR;

/**
 * @author lenovo
 * @description 针对表【sys_user(系统用户)】的数据库操作Service实现
 * @createDate 2024-12-26 19:14:23
 */
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser>
        implements SysUserService {
    @Resource
    private SysDeptMapper sysDeptMapper;
    @Resource
    private SysRoleMapper roleMapper;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Resource
    private SysPermissionMapper permissionMapper;
    @Resource
    private ChargeUserFeignApi userFeignApi;
    @Resource
    private ChargeUserFeignApi chargeUserFeignApi;
    @Autowired
    private RedisIdWorker redisIdWorker;
    @Resource
    private SysUserRoleMapper sysUserRoleMapper;
    @Resource
    private SysUserMapper userMapper;
    @Autowired
    private MinioFileStorageServiceImpl minioFileStorageService;


    /**
     * @return com.zhentao.model.common.dtos.ResponseResult
     * @description admin -- user -- login
     * @author 振涛教育_小Q
     * @date 2024/12/26 19:20
     */
    @Override
    public ResponseResult login(SysUserDto sysUser) {
        // 判断参数是否有效
        if (sysUser == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        // 判断该用户是否存在
        SysUser user = getOne(Wrappers.<SysUser>lambdaQuery()
                .eq(StringUtils.checkValNotNull(sysUser.getUsername()), SysUser::getUsername, sysUser.getUsername()));
        if (user == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.CHARGE_USER_DATA_NOT_EXIST);
        }
        System.err.println(BCrypt.gensalt());
        // 密码加盐加密
        String hashpwPwd = BCrypt.hashpw(sysUser.getPassword(), user.getSalt());
        System.err.println(hashpwPwd);
        // 验证密码是否正确
        if (!hashpwPwd.equals(user.getPassword())) {
            return ResponseResult.errorResult(AppHttpCodeEnum.LOGIN_PASSWORD_ERROR);
        }
        // 创建Dto
        SysUserDto dto = setUserDtoAttribute(user);
        Map<String, Object> map = BeanUtil.beanToMap(dto, new HashMap<>()
                , CopyOptions.create()
                        .setIgnoreNullValue(true)
                        .setFieldValueEditor((fieldName, fieldValue) -> {
                            {
                                // 如果 fieldValue 为 null，返回空字符串或者其他合适的默认值
                                return fieldValue != null ? fieldValue.toString() : "";
                            }
                        }));
        // 存放在redis中
        redisTemplate.opsForValue().set(SYS_USER_LOGIN_CACHE_KEY + user.getId(), JSON.toJSONString(map));
        redisTemplate.expire(SYS_USER_LOGIN_CACHE_EXPIRE_TIME + user.getId(), 30, TimeUnit.MINUTES);
        // 存放全局管理端id 用作工具类 获取用户id
        redisTemplate.opsForValue().set(SYS_USER_LOGIN_CACHE_KEY_ID, user.getId());
        redisTemplate.expire(SYS_USER_LOGIN_CACHE_KEY_ID, 30, TimeUnit.MINUTES);
        // 生成token
        String token = JwtService.createToken(map);
        return ResponseResult.okResult(token);
    }

    /**
     * @param user
     * @return com.zhentao.model.admin.dto.SysUserDto
     * @description 对 userDto 对象设置属性值
     * @author 振涛教育_小Q
     * @date 2024/12/26 20:15
     */
    private SysUserDto setUserDtoAttribute(SysUser user) {
        SysUserDto dto = new SysUserDto();
        BeanUtils.copyProperties(user, dto);
        dto.setPassword("");
        // 查询用户对应的角色 并且和部门
        SysDept depts = sysDeptMapper.selectRoleToDept(user.getId());
        if (depts != null) dto.setDeptName(depts.getName());
        dto.setSexName(SysUserParams.CHARGE_ADMIN_USER_SEX.get(user.getSex()));
        dto.setStatusName(SysUserParams.CHARGE_ADMIN_USER_STATUS_MAP.get(user.getStatus()));
        dto.setCreateWhereName(SysUserParams.CHARGE_ADMIN_USER_WHERE_MAP.get(user.getCreateWhere()));
        SysRole role = roleMapper.selectUserRole(user.getId());
        if (role != null) dto.setRoleName(role.getName());
        // 获取用户权限字符串
        List<String> perms = new ArrayList<>();
        List<SysPermission> permissions = permissionMapper.selectMenuByUserIds(user.getId());
        if (permissions != null && permissions.size() > 0) {
            for (SysPermission permission : permissions) {
                if (!org.springframework.util.StringUtils.isEmpty(permission)) {
                    perms.add(permission.getPerms());
                }
            }
        }
        redisTemplate.opsForValue().set(SYS_PERMISSION_LIST_CACHE_KEY + user.getId(), JSON.toJSONString(perms));
        return dto;
    }

    /**
     * @param
     * @return com.zhentao.model.common.dtos.ResponseResult
     * @description 获取用户信息
     * @author 振涛教育_小Q
     * @date 2024/12/26 20:51
     */
    @Override
    public ResponseResult userInfo() {
        SysUser user = AdminUserThreadLocalUtils.getSysUser();
        if (StringUtils.checkValNull(user)) {
            return ResponseResult.errorResult(AppHttpCodeEnum.CHARGE_USER_DATA_NOT_EXIST);
        }
        SysUser userById = getById(user.getId());
        // 查询用户对应的角色
        SysRole role = roleMapper.selectUserRole(user.getId());
        if(org.springframework.util.StringUtils.isEmpty(role)) return ResponseResult.errorResult(SERVER_ERROR);
        SysUserDto dto = new SysUserDto();
        dto.setAvatar(userById.getAvatar());
        dto.setUsername(userById.getUsername());
        dto.setRoleName(role.getName());
        return ResponseResult.okResult(dto);
    }

    /**
     * @param
     * @return com.zhentao.model.common.dtos.ResponseResult
     * @description 退出登录
     * @author 振涛教育_小Q
     * @date 2024/12/27 8:58
     */
    @Override
    public ResponseResult logout() {
        // 获取登录用户
        SysUser user = AdminUserThreadLocalUtils.getSysUser();
        if (org.springframework.util.StringUtils.isEmpty(user)) {
            return ResponseResult.errorResult(AppHttpCodeEnum.CHARGE_USER_DATA_NOT_EXIST);
        }
        // 删除redis中的缓存
        Boolean delete = redisTemplate.delete(SYS_USER_LOGIN_CACHE_KEY + user.getId());
        // 删除用户的权限字符串
        redisTemplate.delete(SYS_PERMISSION_LIST_CACHE_KEY + user.getId());

        return Boolean.TRUE.equals(delete) ? ResponseResult.okResult(200000, "登出成功") : ResponseResult.errorResult(400, "登出失败");
    }

    @Override
    public PermissionResult csRun() {
        // 获取权限
        AdminUserPermissionUtils permissionUtils = new AdminUserPermissionUtils(redisTemplate);
        ResponseResult result = permissionUtils.hasPermission(SYS_COUPON_SELECT);
        if(!(result.getCode() == 200000)){
            return PermissionResult.ERROR(result.getCode(),result.getErrorMessage());
        }
        return PermissionResult.OK(result.getCode(), result.getErrorMessage());
    }

    @Override
    public PermissionResult getUserList(ChargeUser chargeUser) {
        // 有条件查询
        if (chargeUser != null) {
            List<ChargeUser> userList = chargeUserFeignApi.getUserList();
            List<ChargeUser> chargeUsers = userList.stream()
                    .filter(user -> user.getUserName().contains(chargeUser.getUserName()))
                    .collect(Collectors.toList());
            for (ChargeUser user : chargeUsers) {
                user.setPassword("********");
            }
            return PermissionResult.OK(200000, "查询成功", chargeUsers);
        }
        // 无条件查询
        List<ChargeUser> apiUserList = chargeUserFeignApi.getUserList();
        for (ChargeUser user : apiUserList) {
            user.setPassword("********");
        }
        return PermissionResult.OK(200000, "查询成功", apiUserList);
    }

    @Override
    public PermissionResult addBlackList(Integer userId) {
        //判断参数
        if (userId == null) {
            return PermissionResult.ERROR(400, "参数错误");
        }
        ResponseResult result = chargeUserFeignApi.addBlackList(userId);
        if (result.getCode() == 200000) {
            return PermissionResult.OK(200000, "加入成功");
        }
        return PermissionResult.ERROR(400, "加入失败");
    }

    @Override
    public PermissionResult getRoleList() {
        SysUser sysUser = AdminUserThreadLocalUtils.getSysUser();
        SysUserRole sysUserRole = sysUserRoleMapper.selectOne(Wrappers.<SysUserRole>lambdaQuery()
                .eq(SysUserRole::getUserId, sysUser.getId()));
        SysRole sysRole = roleMapper.selectOne(Wrappers.<SysRole>lambdaQuery().eq(SysRole::getId, sysUserRole.getRoleId()));
        List<SysRole> sysRoles = new ArrayList<>();
        if(sysRole.getName().equals("超级管理员")){
            sysRoles = roleMapper.selectList(null);
        }
        if(sysRole.getName().equals("运营人")){
            return PermissionResult.OK(200000, "您没有权限", null);
        }
        if(sysRole.getName().equals("管理员")){
            sysRoles = roleMapper.selectList(Wrappers.<SysRole>lambdaQuery().ne(SysRole::getName, "超级管理员"));
        }
        return PermissionResult.OK(200000, "查询成功", sysRoles);
    }

    @Override
    @Transactional
    public PermissionResult updateUser(UserDto dto) {
        SysUser sysUser = AdminUserThreadLocalUtils.getSysUser();
        SysUserRole sysUserRole = sysUserRoleMapper.selectOne(Wrappers.<SysUserRole>lambdaQuery()
                .eq(SysUserRole::getUserId, sysUser.getId()));
        SysRole sysRole = roleMapper.selectOne(Wrappers.<SysRole>lambdaQuery().eq(SysRole::getId, sysUserRole.getRoleId()));
        if(sysRole.getName().equals("运营人")){
            return PermissionResult.ERROR(400, "您没有权限");
        }
        //判断参数
        if (dto == null) {
            return PermissionResult.ERROR(400, "参数错误");
        }
        //判断是否存在该用户
        SysUser sysUser1 = userMapper.selectOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUsername, dto.getUserName()));
        if(sysUser1!=null){
            return PermissionResult.ERROR(400, "用户名已存在");
        }
        // 判断用户是否存在
        ChargeUser user = chargeUserFeignApi.getUserInfo(dto.getId());
        if (user == null) {
            return PermissionResult.ERROR(400, "用户不存在");
        }
        // 判断用户是否是黑名单
        if (user.getStatus() == 1) {
            return PermissionResult.ERROR(400, "用户已加入黑名单");
        }
        long adminUserId = redisIdWorker.nextId("admin:user:");
        SysUser userDto = new SysUser();
        userDto.setId(String.valueOf(adminUserId));
        userDto.setAvatar(dto.getAvatarImg());
        userDto.setUsername(dto.getUserName());
        userDto.setNickName(dto.getNickName());
        String gensalt = BCrypt.gensalt();
        System.out.println(gensalt);
        String hashpw = BCrypt.hashpw("12345", gensalt);
        userDto.setSalt(gensalt);
        userDto.setPassword(hashpw);
        userDto.setPhone(dto.getPhone());
        userDto.setEmail(dto.getEmail());
        userDto.setCreateId(sysUser.getId());
        userDto.setCreateTime(new Date());

        userDto.setRealName(dto.getNickName());

        userDto.setStatus(1);
        userDto.setSex(dto.getGender());
        userDto.setDeleted(1);
        Random random = new Random();
        int randomNumber = random.nextInt(3) + 1;
        userDto.setCreateWhere(randomNumber);
        int insert = userMapper.insert(userDto);
        SysUserRole userRole = new SysUserRole();
        userRole.setUserId(String.valueOf(adminUserId));
        userRole.setRoleId(dto.getRoleId());
        userRole.setCreateTime(new Date());
        int insert1 = sysUserRoleMapper.insert(userRole);
        return PermissionResult.OK(200000, "添加成功");
    }


    @Override
    public PermissionResult updateException(ChargeUserExpeciton exception) {
        //检查参数
        if (exception == null){
            return PermissionResult.ERROR(400, "参数错误");
        }
        System.out.println(exception);
        ResponseResult result = chargeUserFeignApi.updateException(exception);
        return PermissionResult.OK(200000, "处理成功");
    }

    @Override
    public PermissionResult getExceptionList() {
        List<ChargeUserExpeciton> exceptionList = chargeUserFeignApi.getExceptionList();
        for (ChargeUserExpeciton chargeUserExpeciton : exceptionList) {
            chargeUserExpeciton.setImagesList(chargeUserExpeciton.getImages().split(","));
        }
        return PermissionResult.OK(200000, "查询成功", exceptionList);
    }

    @Override
    public PermissionResult getGifts() {
        ResponseResult gifts = chargeUserFeignApi.getGifts();
        if (gifts.getCode() == 200000) {
            return PermissionResult.OK(200000, "查询成功", gifts.getData());
        }
        return PermissionResult.ERROR(400, "查询失败");
    }

    @Override
    public PermissionResult saveGift(ChargeUserGift gift) {
        //获取当前登录用户
        SysUser user = AdminUserThreadLocalUtils.getSysUser();
        gift.setCreatedBy(user.getId());
        gift.setCreatedTime(new Date());
        //检查参数
        if (gift == null) {
            return PermissionResult.ERROR(400, "参数错误");
        }
        ResponseResult result = chargeUserFeignApi.saveGift(gift);
        if (result.getCode() == 200000) {
            return PermissionResult.OK(200000, "添加成功");
        }
        return PermissionResult.ERROR(400, "添加失败");
    }

    @Override
    @SneakyThrows
    public PermissionResult uploadImg(MultipartFile file) {
        String path = minioFileStorageService.
                uploadImgFile(UserCommon.CHARGE_USER_REDIS_PREFIX_AVATAR_IMG, file.getOriginalFilename(), file.getInputStream());
        return PermissionResult.OK(200000, "上传成功", path);
    }

    @Override
    public PermissionResult updateGift(ChargeUserGift gift) {
        //检查参数
        if (gift == null) {
            return PermissionResult.ERROR(400, "参数错误");
        }
        ResponseResult result = chargeUserFeignApi.updateGift(gift);
        if (result.getCode() == 200000) {
            return PermissionResult.OK(200000, "修改成功");
        }
        return PermissionResult.ERROR(400, "修改失败");
    }

    @Override
    public PermissionResult deleteGift(Integer id) {
        //检查参数
        if (id == null) {
            return PermissionResult.ERROR(400, "参数错误");
        }
        ResponseResult result = chargeUserFeignApi.deleteGift(id);
        if (result.getCode() == 200000) {
            return PermissionResult.OK(200000, "删除成功");
        }
        return PermissionResult.ERROR(400, "删除失败");
    }


    /**
     * @description  管理端 用户注册数量 活跃数量
     * @author 振涛教育_小Q
     * @date    2024/12/31 16:07
     * @param
     * @return com.zhentao.model.common.dtos.ResponseResult
     */
    @Override
    @SneakyThrows
    public ResponseResult initUserCount() {
        ResponseResult result = userFeignApi.getUserCount();

        if(result.getCode() == 200000){
            ChargeAdminUserVo vo = JSON.parseObject(JSON.toJSONString(result.getData()), ChargeAdminUserVo.class);
            return ResponseResult.okResult(vo);
        }
        return ResponseResult.errorResult(result.getCode(),result.getErrorMessage());
    }



}




